ProductInfo.vue
測試 ProductList.vue,在 ./tests/unit/views 底下新增 ProductInfo.spec.js 檔案
分別測試:
1.created 後的資料更動
使用到 ProductService,引用方法參考 ProductList,因為需要取得的商品資料需要依據路由的 id 判斷,在
這裡需要針對路由處理
const $route = {
path: '/product/1',
params: { id: 1 },
};
在建立實體時加入模擬的 $route
const wrapper = shallowMount(ProductInfo, { mocks: { $route } });
完整測試碼
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import ProductInfo from '@/views/ProductInfo';
const $route = {
path: '/product/1',
params: { id: 1 },
};
const mockProduct = {
id: 1,
name: 'Product I',
imgUrl: 'https://images.pexels.com/photos/1200458/pexels-photo-1200458.jpeg?
auto=compress&cs=tinysrgb&h=350',
desc: 'Description',
price: 20.00,
};
jest.mock('@/services/product-service', () => ({
get: () => mockProduct,
}));
Vue.filter('currency', value => value);
describe('ProductInfo.vue', () => {
it('sets the correct data', () => {
const wrapper = shallowMount(ProductInfo, { mocks: { $route } });
expect(wrapper.vm.product).toEqual(mockProduct);
});
});
2.computed 內的屬性
it('compute correct amount', () => {
const input = wrapper.find('#qty');
input.element.value = 2;
input.trigger('input');
expect(wrapper.vm.amount).toBeCloseTo(40.00);
});
因為 wrapper 在每個測試方法中都是用同樣的方式實體化,可以用 beforeEach 減少在每個方法都要加入實
體化的程式碼,完整測試碼:
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import ProductInfo from '@/views/ProductInfo';
const $route = {
path: '/product/1',
params: { id: 1 },
};
const mockProduct = {
id: 1,
name: 'Product I',
imgUrl: 'https://images.pexels.com/photos/1200458/pexels-photo-1200458.jpeg?
auto=compress&cs=tinysrgb&h=350',
desc: 'Description',
price: 20.00,
};
jest.mock('@/services/product-service', () => ({
get: () => mockProduct,
}));
Vue.filter('currency', value => value);
describe('ProductInfo.vue', () => {
let wrapper;
beforeEach(() => {
wrapper = shallowMount(ProductInfo, { mocks: { $route } });
});
it('sets the correct data', () => {
expect(wrapper.vm.product).toEqual(mockProduct);
});
it('compute correct amount', () => {
const input = wrapper.find('#qty');
input.element.value = 2;
input.trigger('input');
expect(wrapper.vm.amount).toBeCloseTo(40.00);
});
});
3.methods 內的方法
由於無法實際測試回到上一頁的事件,因此僅確認方法是否成功執行
it('trigger onBackClick method', () => {
wrapper.setMethods({ onBackClick: jest.fn() });
wrapper.find('button').trigger('click');
expect(wrapper.vm.onBackClick).toHaveBeenCalledTimes(1);
});
完整測試碼
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import ProductInfo from '@/views/ProductInfo';
const mockProduct = {
id: 1,
name: 'Product I',
imgUrl: 'https://images.pexels.com/photos/1200458/pexels-photo-1200458.jpeg?
auto=compress&cs=tinysrgb&h=350',
desc: 'Description',
price: 20.00,
};
jest.mock('@/services/product-service', () => ({
get: () => mockProduct,
}));
const $route = {
path: '/product/1',
params: { id: 1 },
};
Vue.filter('currency', value => value);
describe('ProductInfo.vue', () => {
let wrapper;
beforeEach(() => {
wrapper = shallowMount(ProductInfo, { mocks: { $route } });
});
it('sets the correct data', () => {
expect(wrapper.vm.product).toEqual(mockProduct);
});
it('compute correct amount', () => {
const input = wrapper.find('#qty');
input.element.value = 2;
input.trigger('input');
expect(wrapper.vm.amount).toBeCloseTo(40.00);
});
it('trigger onBackClick method', () => {
wrapper.setMethods({ onBackClick: jest.fn() });
wrapper.find('button').trigger('click');
expect(wrapper.vm.onBackClick).toHaveBeenCalledTimes(1);
});
});
Currency filter
僅須測試回傳值是否正確
import Currency from '@/filters/Currency';
describe('Currency.js', () => {
it('return correct content', () => {
const input = 10.05;
expect(Currency(input)).toMatch('$ 10.05');
});
});